package com.example.demo.service;

import com.example.demo.Exception.CodeInvalidException;
import com.example.demo.Exception.ProblemNotFoundException;
import com.example.demo.compile.Answer;
import com.example.demo.compile.Question;
import com.example.demo.compile.Task;
import com.example.demo.dao.mapper.AcMapper;
import com.example.demo.dao.mapper.ProblemMapper;
import com.example.demo.dao.pojo.ProblemInfo;
import com.example.demo.dao.pojo.UserInfo;
import com.example.demo.vo.CompileRequest;
import com.example.demo.vo.CompileResponse;
import com.example.demo.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class CompileService {
    @Autowired
    private ProblemMapper problemMapper;

    @Autowired
    private ThreadService threadService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private AcMapper acMapper;

    public Result compile(CompileRequest compileRequest) {
        CompileResponse compileResponse = new CompileResponse();
        try {
            // 1. 获取编写的代码
            int id = compileRequest.getId();
            String code = compileRequest.getCode();
            //    如果输入的代码为空，则不合法
            if (code == null) {
                throw new CodeInvalidException();
            }

            // 2. 根据 id 从数据库中查找到题目的详情 ==》得到测试代码
            ProblemInfo problemInfo = problemMapper.selectOneById(id);
            if (problemInfo == null) {
                throw new ProblemNotFoundException();
            }
            String testCode = problemInfo.getTestCode();

            // 3. 将用户提交的代码和测试代码进行组装
            int index = code.lastIndexOf("}");
            //    找不到编辑代码的最后一个 }
            if(index == -1){
                throw new CodeInvalidException();
            }
            String subCode = code.substring(0, index);
            String finalCode = subCode + testCode + "\n}";
            System.out.println("用户的当前工作目录: "+System.getProperty("user.dir"));

            System.out.println(finalCode);
            // 4. 创建一个 Task 实例，调用里面的 compileRun 方法编译运行
            Task task = new Task();
            Question question = new Question();
            question.setCode(finalCode);
            Answer answer = task.compileAndRun(question);

            // 5. 根据 Task 的运行结果，编辑 HTTP 响应
            compileResponse.setError(answer.getError());
            compileResponse.setReason(answer.getReason());
            compileResponse.setStdout(answer.getStdout());

            // 6. 根据编译运行的结果，增加题目的提交次数和 ac 次数
            //    但是更新题目会进行加锁，阻塞其它的读操作，性能就会比较低
            //    没办法降低枷锁的耗时，但是如果更新出问题，会影响其它流程
            //    使用线程池，把更新操作放到线程池中
            threadService.updateProblemVisitCount(problemMapper, problemInfo, answer);

            // 7. 根据编译运行的结果，增加 ac 表中的用户和题目的关系
            String token = compileRequest.getToken();
            UserInfo userInfo = tokenService.checkToken(token);
            threadService.updateAc(acMapper, userInfo, problemInfo, answer);

        } catch(ProblemNotFoundException e){
            compileResponse.setError(3);
            compileResponse.setReason("找不到指定 id 的代码" + compileRequest.getId());
        } catch (CodeInvalidException e){
            compileResponse.setError(3);
            compileResponse.setReason("提交代码不符合规范");
        } finally {
            return Result.success(compileResponse);
        }
    }
}
